package com.meme.io.editor;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.meme.editor.model.sprite2d.*;
import com.meme.util.XmlUtil;
import com.meme.util.FileUtil;

public class AnimXmlFileLoader 
{
	static Logger logger = Logger.getLogger (AnimXmlFileLoader.class);
	
	String mAnimXmlFilename;
	

	public Sprite2dFile loadFromXmlDocument (Document document, String filename)
	{
		mAnimXmlFilename = filename;
		
		Sprite2dFile sprite2dFile = new Sprite2dFile ();
		
		loadAnimXmlFile (document, sprite2dFile);

		sprite2dFile.setHostFilename (filename);

		return sprite2dFile;
	}
	
	public Sprite2dFile loadFromFile (String filename)
	{
		Document document = XmlUtil.loadXmlFile (filename);
		
		Sprite2dFile sprite2dFile = loadFromXmlDocument (document, filename);
		
		return sprite2dFile;
	}
	
//---------------------------------------------------------------------------	
// 
//---------------------------------------------------------------------------	
	
	void loadAnimXmlFile (Document document, Sprite2dFile sprite2dFile)
	{
		Element animationElement = XmlUtil.getChildElementByName (document, "Animation");
		
		String version = animationElement.getAttribute("version");
		
		// module image set
		{	
			ModuleImage moduleImage = sprite2dFile.createNewModuleImage();			
			moduleImage.setName ( "image" );
			
			
			String imageFilename = FileUtil.getFullPathFilename(
					animationElement.getAttribute("image"), 
					mAnimXmlFilename );
			moduleImage.setImageFilename(imageFilename);
			
			if ( ! moduleImage.isValid() )
			{
				imageFilename = FileUtil.getFullPathFilename(
						FileUtil.getFilename ( animationElement.getAttribute("image") ), 
						mAnimXmlFilename );					
				moduleImage.setImageFilename(imageFilename);
			}
		}
		
		// pure module group
		{
			PureModuleGroup pureModuleGroup = sprite2dFile.createNewPureModuleGroup();
			pureModuleGroup.setName("Pure Modules");
			
			pureModuleGroup.setModuleImage( (ModuleImage)sprite2dFile.getModuleImageSet().getChildByIndex(0));
			
			Element element = XmlUtil.getChildElementByName(animationElement, "Modules");		
			Element[] moduleElements = XmlUtil.getChildElementsByName(element, "Module");		
			
			int index = 0;
			for (Element moduleElement : moduleElements)
			{
				PureModule pureModule = pureModuleGroup.createNewModule();
				
				pureModule.setName ( "Module_" + ( index ++ ) );
				pureModule.setX ( XmlUtil.parseAttributeAsInt(moduleElement, "x") );
				pureModule.setY ( XmlUtil.parseAttributeAsInt(moduleElement, "y") );
				pureModule.setWidth  ( XmlUtil.parseAttributeAsInt(moduleElement, "w") );
				pureModule.setHeight ( XmlUtil.parseAttributeAsInt(moduleElement, "h") );	
			}
		}
		
		// composited mdoule group
		{
			CompositedModuleGroup compositedModuleGroup = sprite2dFile.createNewCompositedModuleGroup();
			compositedModuleGroup.setName("Compostied Modules");
			
			Element element = XmlUtil.getChildElementByName(animationElement, "Frames");		
			Element[] frameElements = XmlUtil.getChildElementsByName(element, "Frame");		
			
			for (Element frameElement : frameElements)
			{
				CompositedModule compositedModule = compositedModuleGroup.createNewCompositedModule();
				compositedModule.setName (frameElement.getAttribute("name"));
				
				Element[] spriteElements = XmlUtil.getChildElementsByName(frameElement, "Sprite");	
				
				int index = 0;
				for (Element spriteElement : spriteElements)
				{
					ModulePart modulePart = compositedModule.createNewModulePart();
					modulePart.setName ( "Part_" + ( index ++ ) );
					
					int partRefedModuleID = XmlUtil.parseAttributeAsInt(spriteElement, "module_id");
					Module partRefedModule = partRefedModuleID < 0 ? null : (Module) ( (ModuleGroup) sprite2dFile.getPureModuleGroupSet().getChildByIndex(0) ).getChildByIndex(partRefedModuleID);
					boolean flipX = XmlUtil.parseAttributeAsFloat(spriteElement, "m00") < 0;
					boolean flipY = XmlUtil.parseAttributeAsFloat(spriteElement, "m11") < 0;
					int offsetX = (int) XmlUtil.parseAttributeAsFloat(spriteElement, "m02");
					int offsetY = (int) XmlUtil.parseAttributeAsFloat(spriteElement, "m12");
//					if ( flipX ) offsetX = - offsetX - partRefedModule.getWidth();
//					if ( flipY ) offsetY = - offsetY - partRefedModule.getHeight();
					
					modulePart.setModule ( partRefedModule );
					modulePart.setOffsetX ( offsetX );
					modulePart.setOffsetY ( offsetY );
					modulePart.setFlipX ( flipX );
					modulePart.setFlipY ( flipY );
					modulePart.setPaletteID ( 0 );
					modulePart.setFlags ( 0 );
				}
			}
		}
		
		// Animated Module Group
		{
			AnimatedModuleGroup animatedModuleGroup = sprite2dFile.createNewAnimatedModuleGroup();
			animatedModuleGroup.setName("Animated Modules");
			
			Element element = XmlUtil.getChildElementByName(animationElement, "Actions");		
			Element[] actionElements = XmlUtil.getChildElementsByName(element, "Action");		
			
			for (Element actionElement : actionElements)
			{
				AnimatedModule animatedModule = animatedModuleGroup.createNewAnimatedModule();
				animatedModule.setName (actionElement.getAttribute("name"));
				
				Element mechElement = XmlUtil.getChildElementByName(actionElement, "MechModel");
				float ax = XmlUtil.parseAttributeAsFloat(mechElement, "ax") / 256;
				float ay = XmlUtil.parseAttributeAsFloat(mechElement, "ay") / 256;
				float vx = XmlUtil.parseAttributeAsFloat(mechElement, "vx") / 256;
				float vy = XmlUtil.parseAttributeAsFloat(mechElement, "vy") / 256;
				
				float offsetX = 0;
				float offsetY = 0;
				
				boolean velocityIsAwalysZero = ax == 0f && ay == 0f && vx == 0f && vy == 0f;
				
				Element[] sequenceElements = XmlUtil.getChildElementsByName(actionElement, "Sequence");	
				
				int index = 0;
				for (Element sequenceElement : sequenceElements)
				{
					int partRefedModuleID = XmlUtil.parseAttributeAsInt(sequenceElement, "id");
					Module partRefedModule = (Module) ( (ModuleGroup) sprite2dFile.getCompositedModuleGroupSet().getChildByIndex(0) ).getChildByIndex(partRefedModuleID);
					int duration = XmlUtil.parseAttributeAsInt(sequenceElement, "duration");
					
					int dur, count;
					if ( duration <= 1 || velocityIsAwalysZero )
					{
						dur = 1;
						count = 1;
					}
					else
					{
						dur = 1;
						count = duration;
					}
					
					while (-- count >= 0)
					{
						ModuleSequence moduleSequence = animatedModule.createNewModuleSequence();
						moduleSequence.setName ( "Sequence_" + ( index ++ ) );
						
						moduleSequence.setModule ( partRefedModule );
						moduleSequence.setOffsetX ( (int) offsetX );
						moduleSequence.setOffsetY ( (int) offsetY );
						moduleSequence.setFlipX ( false );
						moduleSequence.setFlipY ( false );
						moduleSequence.setPaletteID ( 0 );
						moduleSequence.setFlags ( 0 );
						moduleSequence.setDuration ( dur );
						
						
						offsetX += vx;
						offsetY += vy;
						vx += ax;
						vy += ay;
					}
				}
			}
		}

	}
	
}
